import time
import json
import atexit
import signal
import threading
import copy
import re
import logging

logger = logging.getLogger(__name__)
kk = re.compile(r'\d+\.?\d+|\d+|-\d+\.?\d+')

resultModel = {"x": 0.0, "y": 0.0,
          "h": 0.0, "v": 0.0,
          "m": -1, "th": 0.0,
          "br": 0.0, "st": 0.0,
          "soc": 0.0, "t": 0}

class SharedVariable:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:
                    cls._instance = super(SharedVariable, cls).__new__(cls)
                    cls._instance._initialized = False
        return cls._instance

    def __init__(self):  # variable["m"]是遥控器状态，初始化为1（遥控模式） 0为录制模式，遥控器上的回放档在单片机中体现，在该程序中不涉及
        if not self._initialized:
            self.variable = copy.deepcopy(resultModel)
            self.lock = threading.Lock()
            self._initialized = True


    def set(self, value):
        with self.lock:
            self.variable = value

    def get(self):
        with self.lock:
            return copy.deepcopy(self.variable)

    def update_data(self, data: str):
        xyv = kk.findall(data)
        result = copy.deepcopy(resultModel)
        if len(xyv) == 9:
            result["x"] = float(xyv[0])
            result["y"] = float(xyv[1])
            result["h"] = float(xyv[2])
            result["v"] = float(xyv[3])
            result["m"] = int(xyv[4])
            result["th"] = float(xyv[5])
            result["br"] = float(xyv[6])
            result["st"] = float(xyv[7])
            result["soc"] = float(xyv[8])
            self.set(result)


class VehicleStateLogger:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:
                    cls._instance = super(VehicleStateLogger, cls).__new__(cls)
                    cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        if not self._initialized:
            self.current_data = {
                "timestamp": 0.0,
                "mode": 0,
                "state": dict(),
                "mpc": dict(),
                "lqr": dict(),
                "track": dict()
            }
            self.state = SharedVariable()
            self.log = []
            self.lock = threading.Lock()
            self._initialized = True
            self.last_saved_index = 0
            self.log_file_path = None
            self.file = None
            # 注册退出处理函数

            atexit.register(self._save_on_exit)
            signal.signal(signal.SIGINT, self._signal_handler)
            signal.signal(signal.SIGTERM, self._signal_handler)

            # 启动后台线程定期保存日志
            self.auto_save_interval = 3  # 自动保存间隔，单位为秒
            self.auto_save_thread = threading.Thread(target=self._auto_save, daemon=True)
            self.auto_save_thread.start()

    def load_file(self, file: str = None):
        self.log_file_path = file
        self.file = open(file, 'a+')
        if self.file.tell() == 0:
            self.file.write('[\n')

    def _save_on_exit(self):
        """程序退出时自动保存日志"""
        self.save_log(clear_after_save=True)
        self._cleanup(True)

    def _signal_handler(self, signum, frame):
        """捕获信号并保存日志"""
        logger.info(f"Signal {signum} received, saving log...")
        self.save_log(clear_after_save=True)
        self._cleanup(True)
        exit(0)

    def _auto_save(self):
        """后台线程定期自动保存日志"""
        while True:
            time.sleep(self.auto_save_interval)
            self.save_log(clear_after_save=True)

    def load_track(self, x: list, y: list, h: list, v: list, t:list):
        self.current_data.update({
            "track": {"x": [],
                      "y": [],
                      "h": [],
                      "v": [],
                      "t": []}
        })

    def update_data(self, mpc:dict = None, lqr: dict = None):
        if mpc is not None:
            self.current_data["mpc"] = copy.deepcopy(mpc)
        if lqr is not None:
            self.current_data["lqr"] = copy.deepcopy(lqr)

    def record_timestamp(self):
        with self.lock:
            timestamps = time.time()
            state =  self.state.get()
            self.current_data["timestamp"] = timestamps
            self.current_data["mode"] = state["m"]
            self.current_data["state"] = state
            self.log.append(copy.deepcopy(self.current_data))
            self.current_data["mpc"] = dict()
            self.current_data["lqr"] = dict()
            self.current_data["track"] = dict()

    def save_log(self, clear_after_save=False):
        with self.lock:
            # 只保存从上次保存后的新数据
            new_entries = self.log[self.last_saved_index:]
            if not new_entries:
                return  # 如果没有新数据则不保存
            try:
                # 追加新数据到文件
                for i, entry in enumerate(new_entries):
                    if self.file.tell() > 2:  # 不是第一个条目，添加逗号
                        self.file.write(',\n')
                    json.dump(entry, self.file)
                self.file.flush()
                # 更新保存的索引
                self.last_saved_index = len(self.log)
                if clear_after_save:
                    self.log.clear()
                    self.last_saved_index = 0
            except Exception as e:
                print(f"Error saving log: {e}")

    def _cleanup(self, final=False):
        """清理函数，在程序退出时关闭文件"""
        with self.lock:
            if self.file:
                if final:
                    self.file.seek(0, 2)  # 确保文件指针在末尾
                    self.file.write('\n]')
                self.file.close()
                self.file = None
